package com.tbynet.jwp.web.config;

import java.sql.Connection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.druid.filter.stat.StatFilter;
import com.alibaba.druid.wall.WallFilter;
import com.jfinal.config.Constants;
import com.jfinal.config.Handlers;
import com.jfinal.config.Interceptors;
import com.jfinal.config.Plugins;
import com.jfinal.config.Routes;
import com.jfinal.json.MixedJsonFactory;
import com.jfinal.kit.Prop;
import com.jfinal.kit.PropKit;
import com.jfinal.plugin.activerecord.ActiveRecordPlugin;
import com.jfinal.plugin.activerecord.SqlReporter;
import com.jfinal.plugin.druid.DruidPlugin;
import com.jfinal.plugin.druid.DruidStatViewHandler;
import com.jfinal.plugin.druid.IDruidStatViewAuth;
import com.jfinal.plugin.ehcache.EhCachePlugin;
import com.jfinal.template.Engine;
import com.tbynet.jwp.Directives;
import com.tbynet.jwp.framework.aop.AopMappingPlugin;
import com.tbynet.jwp.framework.core.JwpConfig;
import com.tbynet.jwp.framework.core.JwpService;
import com.tbynet.jwp.framework.directive.CompareDirective;
import com.tbynet.jwp.framework.interceptor.ExceptionInterceptor;
import com.tbynet.jwp.framework.interceptor.JwpRepositoryCallInterceptor;
import com.tbynet.jwp.framework.kit.CookieKit;
import com.tbynet.jwp.model.Users;
import com.tbynet.jwp.model._MappingKit;

public class WebConfig extends JwpConfig {
	
	private static Prop p = loadConfig();
	private WallFilter wallFilter;

	@Override
	public void doConfigConstant(Constants me) {
		me.setDevMode(p.getBoolean("devMode", false));
		me.setJsonFactory(MixedJsonFactory.me());
		me.setError404View("/404.html");
		me.setBaseUploadPath("wp-content/uploads");
		me.setBaseDownloadPath("/");
		me.setInjectDependency(true);
		me.setInjectSuperClass(true);
	}

    @Override
    public void doConfigInterceptor(Interceptors me) {
        // 全局异常拦截器
        me.add(new ExceptionInterceptor());

        // JwpService 调用限制拦截器，只能被JwpManager子类调用
        Set<Class<?>> allowedParents = Collections.singleton(JwpService.class);

        // 限制多个Service包
        Set<String> serviceRestrictPackages = new HashSet<>();
        serviceRestrictPackages.add("com.tbynet.jwp.service");

        // 校验多个Manager包
        Set<String> callerCheckPackages = new HashSet<>();
        callerCheckPackages.add("com.tbynet.jwp.manager");

        JwpRepositoryCallInterceptor interceptor = JwpRepositoryCallInterceptor.create(
                allowedParents,
                serviceRestrictPackages,
                callerCheckPackages
        );
        me.add(interceptor);
    }

    @Override
    public void doConfigRoute(Routes me) {
        me.add(new com.tbynet.jwp.admin.AdminRoutes());
        me.add(new com.tbynet.jwp.portal.PortalRoutes());

        me.scan("com.tbynet.jwp.web").setBaseViewPath("/WEB-INF/admin");
    }

    @Override
    public void doConfigPlugin(Plugins me) {
        DruidPlugin druidPlugin = getDruidPlugin();
        wallFilter = new WallFilter();              // 加强数据库安全
        wallFilter.setDbType("mysql");
        druidPlugin.addFilter(wallFilter);
        druidPlugin.addFilter(new StatFilter());    // 添加 StatFilter 才会有统计数据
        me.add(druidPlugin);

        ActiveRecordPlugin arp = new ActiveRecordPlugin(druidPlugin);
        arp.setTransactionLevel(Connection.TRANSACTION_READ_COMMITTED);
        _MappingKit.mapping(arp);
        me.add(arp);
        if (p.getBoolean("devMode", false)) {
            // 输出完整SQL，包括参数值
            arp.setShowSql(true);
            // 使用SqlReporter，可以输出带参数值的SQL
            SqlReporter.setLog(true);
        }

        me.add(new EhCachePlugin());

        AopMappingPlugin amp = new AopMappingPlugin("com.tbynet.jwp");
        me.add(amp);
    }

	@Override
	public void doConfigEngine(Engine me) {
        // 以下配置支持静态方法调用表达式：com.jfinal.kit.StrKit::isBlank('abc')
        me.setStaticMethodExpression(true);

        // 以下配置支持静态属性访问表达式：com.jfinal.core.Constant::JFINAL_VERSION
        me.setStaticFieldExpression(true);

		me.addDirective("compare", CompareDirective.class);

        new Directives(me);

	}

	@Override
	public void doConfigHandler(Handlers me) {
		me.add(new DruidStatViewHandler("/druid", new IDruidStatViewAuth() {
			
			@Override
			public boolean isPermitted(HttpServletRequest request) {
				String sessionId = CookieKit.getCookie(request, Users.sessionIdName);
				if (null == sessionId) {
					return false;
				}

				return true;
			}
			
		}));

		me.add(new com.tbynet.jwp.admin.AdminHandler());
		me.add(new com.tbynet.jwp.portal.PortalHandler());
	}


	private static Prop loadConfig() {
		try {
			// 优先加载生产环境配置文件
			return PropKit.use("config.properties");
		} catch (Exception e) {
			// 找不到生产环境配置文件，再去找开发环境配置文件
			return PropKit.use("config.dev.properties");
		}
	}
	
	private static DruidPlugin getDruidPlugin() {
		return new DruidPlugin(p.get("jdbcUrl"), p.get("user"), p.get("password").trim());
	}

}
